//
//  main.m
//  Oc02_实例变量可见度_方法
//
//  Created by dllo on 16/2/25.
//  Copyright © 2016年 Apon. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
#pragma mark - 知识点1.实例变量(成员)可见度

/**
 * 三种 : @public @protected @private
 * 默认 : @protectcd
 * 3种之前的区别:@public :  本类(->)可以直接访问
                          子类可以直接访问
                          其他类 可以直接访问
               @protected : 本类 可以直接访问
                            子类 可以直接访问
                            其他类 不可以直接访问
               @private : 本类 可以直接访问
                          子类 不可以直接访问
                          其他类 不可以直接访问
 * 详见 Person.h文件
*/
#pragma mark - 知识点2.方法
/**
 * [接收者 消息]
 *
 * 接收者 : 类和对象.
 * 消息(方法): 类方法(+)和对象方法(-).
 * 
 * 详见 Person.h文件.
 */
#pragma mark - 知识点3.setter, getter 方法
/**
 * 一个实例变量要有一对setter, getter方法.
 * setter 方法目的,对实例变量赋值.
 * getter 方法目的,对实例变量取值.
 *
 * 详见Person.h 文件.
 */
#if 0
    Person *per1 = [[Person alloc] init];
    /** 调用setter方法 */
    [per1 setName:@"zhu"];
    /** 调用getter方法 */
    [per1 name];
    
    NSString *str1 = [per1 name];
    NSLog(@"str1: %@", str1);

    //创建per2对象
    Person *per2 = [[Person alloc] init];
    [per2 setName: @"TOM"];
    [per2 setName:@"lisi"];
    NSLog(@"%@", [per2 name]);
    
    //注意: 下面的per3并没有开辟新的内存空间,只是指针指向了per2内存首地址
    Person *per3 = per2;
    NSLog(@"%@", per3.name);
#pragma mark - 知识点4.继承
    /**
     * 子类继承父类 所有的实例变量的方法.
     * OC中, 只有子类和父类两层.
     * OC中是单项继承.
     * 继承有传递性.
     *
     * Student类继承于Person类, CollegeStudent类继承于Student类.
     * 详见Student, CollegeStudent类文件
     */
    //创建学生对象
    Student *stu1 = [[Student alloc] init];
    //setname方法是从父类继承下来的
    [stu1 setName:@"wang"];
    [stu1 Name:@"wang" Sex:@"男" Age:18];
    [stu1 sayHi];
#pragma mark - 知识点5. 重写父类方法(overwrite)
/**
 * 父类方法无法满足子类需求.
 * 重写父类方法一般是在父类方法的基础上,添加新的代码段.
 * 详见student.m文件.
 */
    //创建一个student对象
    Student *stu3 = [[Student alloc] init];
    [stu3 Name:@"wangwu" Sex:@"wangwu" Age:20];
    [stu3 setGrade:80];
    [stu3 setclassroomName:@"160101"];
    
    //调用sayhi方法
    [stu3 sayHi];
#pragma mark - 知识点6 重写初始化方法.
    
/**
 * Person类重写 父类的 init方法.
 * 详见Person.m文件
 */
    //创建一个person对象
    Person *per1 = [[Person alloc] init];
    [per1 sayHi];
    //对student
    Student *stu1 = [[Student alloc] init];
    [stu1 sayHi];
#pragma mark - 知识点7.自定义初始化方法
/**
 * 需求: 通过一个方法,实现了初始化同时给某些变量赋值
 * 详见  person.h, person.m文件
 */
    Person *per1 = [[Person alloc] initWithName:@"tom"];
    [per1 sayHi];
    Person *per2 = [[Person alloc]initWithName:@"zhu" sex:@"male" age:20
                    ];
    [per2 sayHi];
#endif
#pragma mark - 知识点8.构造器
    /** 
     * 构造器就是方法.
     * +方法.
     * 封装了对象创建和初始化过程.
     * 详见Person类文件.
     */
    //创建对象
    Person *per1 = [Person person];
    //[per1 sayHi];
    Person *per2 = [Person personWithName:@"z" sex:@"a" age:10];
    [per2 sayHi];
    return 0;
}
